package io.github.echarts.model.geometry;

/**
 * 表示弧线路径片段
 * 对应SVG路径中的A命令
 */
public class ArcTo implements PathSegment {
    
    /**
     * X轴半径
     */
    private final double radiusX;
    
    /**
     * Y轴半径
     */
    private final double radiusY;
    
    /**
     * X轴旋转角度（弧度）
     */
    private final double xAxisRotation;
    
    /**
     * 是否选择大弧（大于180度的弧）
     */
    private final boolean largeArcFlag;
    
    /**
     * 是否顺时针方向绘制
     */
    private final boolean sweepFlag;
    
    /**
     * 终点
     */
    private final Point end;
    
    /**
     * 创建ArcTo路径片段
     * 
     * @param radiusX X轴半径
     * @param radiusY Y轴半径
     * @param xAxisRotation X轴旋转角度（弧度）
     * @param largeArcFlag 是否选择大弧
     * @param sweepFlag 是否顺时针方向绘制
     * @param end 终点
     */
    public ArcTo(double radiusX, double radiusY, double xAxisRotation,
                boolean largeArcFlag, boolean sweepFlag, Point end) {
        if (end == null) {
            throw new IllegalArgumentException("终点不能为null");
        }
        if (radiusX < 0 || radiusY < 0) {
            throw new IllegalArgumentException("半径不能为负值");
        }
        
        this.radiusX = radiusX;
        this.radiusY = radiusY;
        this.xAxisRotation = xAxisRotation;
        this.largeArcFlag = largeArcFlag;
        this.sweepFlag = sweepFlag;
        this.end = end;
    }
    
    /**
     * 创建ArcTo路径片段
     * 
     * @param radiusX X轴半径
     * @param radiusY Y轴半径
     * @param xAxisRotation X轴旋转角度（弧度）
     * @param largeArcFlag 是否选择大弧
     * @param sweepFlag 是否顺时针方向绘制
     * @param x 终点X坐标
     * @param y 终点Y坐标
     */
    public ArcTo(double radiusX, double radiusY, double xAxisRotation,
               boolean largeArcFlag, boolean sweepFlag, double x, double y) {
        this(radiusX, radiusY, xAxisRotation, largeArcFlag, sweepFlag, new Point(x, y));
    }
    
    /**
     * 获取X轴半径
     * 
     * @return X轴半径
     */
    public double getRadiusX() {
        return radiusX;
    }
    
    /**
     * 获取Y轴半径
     * 
     * @return Y轴半径
     */
    public double getRadiusY() {
        return radiusY;
    }
    
    /**
     * 获取X轴旋转角度
     * 
     * @return X轴旋转角度（弧度）
     */
    public double getXAxisRotation() {
        return xAxisRotation;
    }
    
    /**
     * 是否选择大弧
     * 
     * @return 是否选择大弧
     */
    public boolean isLargeArcFlag() {
        return largeArcFlag;
    }
    
    /**
     * 是否顺时针方向绘制
     * 
     * @return 是否顺时针方向绘制
     */
    public boolean isSweepFlag() {
        return sweepFlag;
    }
    
    /**
     * 获取终点
     * 
     * @return 终点
     */
    public Point getEnd() {
        return end;
    }
    
    @Override
    public PathSegmentType getType() {
        return PathSegmentType.ARC_TO;
    }
    
    @Override
    public String toSvgPathData() {
        return "A" + radiusX + "," + radiusY + " " +
               Math.toDegrees(xAxisRotation) + " " +
               (largeArcFlag ? "1" : "0") + "," +
               (sweepFlag ? "1" : "0") + " " +
               end.getX() + "," + end.getY();
    }
    
    @Override
    public Rectangle getBounds(Point startPoint) {
        if (startPoint == null) {
            // 如果没有起始点，只能返回终点的零尺寸矩形
            return new Rectangle(end.getX(), end.getY(), 0, 0);
        }
        
        // 计算弧线的精确边界是复杂的，需要考虑椭圆的旋转、起点和终点的位置等因素
        // 这里我们采用一个简化的方法：使用包含起点和终点的矩形，并适当扩展
        double minX = Math.min(startPoint.getX(), end.getX());
        double minY = Math.min(startPoint.getY(), end.getY());
        double maxX = Math.max(startPoint.getX(), end.getX());
        double maxY = Math.max(startPoint.getY(), end.getY());
        
        // 根据半径和弧的类型适当扩展边界
        double expandX = radiusX;
        double expandY = radiusY;
        
        if (largeArcFlag) {
            // 如果是大弧，边界可能需要更大的扩展
            expandX *= 2;
            expandY *= 2;
        }
        
        minX -= expandX;
        minY -= expandY;
        maxX += expandX;
        maxY += expandY;
        
        return new Rectangle(minX, minY, maxX - minX, maxY - minY);
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        
        ArcTo arcTo = (ArcTo) o;
        
        if (Double.compare(arcTo.radiusX, radiusX) != 0) return false;
        if (Double.compare(arcTo.radiusY, radiusY) != 0) return false;
        if (Double.compare(arcTo.xAxisRotation, xAxisRotation) != 0) return false;
        if (largeArcFlag != arcTo.largeArcFlag) return false;
        if (sweepFlag != arcTo.sweepFlag) return false;
        return end.equals(arcTo.end);
    }
    
    @Override
    public int hashCode() {
        int result;
        long temp;
        temp = Double.doubleToLongBits(radiusX);
        result = (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(radiusY);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(xAxisRotation);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        result = 31 * result + (largeArcFlag ? 1 : 0);
        result = 31 * result + (sweepFlag ? 1 : 0);
        result = 31 * result + end.hashCode();
        return result;
    }
    
    @Override
    public String toString() {
        return "ArcTo{" +
                "radiusX=" + radiusX +
                ", radiusY=" + radiusY +
                ", xAxisRotation=" + xAxisRotation +
                ", largeArcFlag=" + largeArcFlag +
                ", sweepFlag=" + sweepFlag +
                ", end=" + end +
                '}';
    }
} 